package com.joker.orange.service.impl;

import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.crypto.SecureUtil;
import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.joker.common.enums.MemberLevelEnum;
import com.joker.common.helper.LoginHelper;
import com.joker.orange.domain.*;
import com.joker.orange.domain.bo.OrderNotifyBo;
import com.joker.orange.domain.bo.UserBuyOrderBo;
import com.joker.orange.domain.vo.*;
import com.joker.orange.mapper.*;
import com.joker.orange.service.IOrderInfoService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.net.MalformedURLException;
import java.net.URL;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.*;

/**
 * MemberOrderServiceImpl
 *
 * @author Joker
 * @date 2024/6/16 09:14
 */

@Slf4j
@RequiredArgsConstructor
@Service
public class OrderInfoServiceImpl implements IOrderInfoService {

    private final static String mid = "M200082";
    private final static String clientIp = "154.213.68.33";
    private final static String secret = "8525c695f8e016e53fbbadf265907ee4";
    private final static String notifyUrlByMemberOrder = "http://123.57.66.62/order/orderNotify";
    private final static String payUrl = "http://qzbf8y134dxd.itsfpy.com/api/services/app/Api_PayOrder/CreateOrderPay";

    private final MemberOrderMapper memberOrderMapper;
    private final UserInfoMapper userInfoMapper;
    private final DiamondConsumeRecordMapper diamondConsumeRecordMapper;
    private final MemberInfoMapper memberInfoMapper;
    private final DiamondRechargeMapper diamondRechargeMapper;
    private final NovelInfoMapper novelInfoMapper;
    private final NovelChapterMapper novelChapterMapper;
    private final CaricatureInfoMapper caricatureInfoMapper;
    private final CaricatureChapterMapper caricatureChapterMapper;
    private final VideoInfoMapper videoInfoMapper;
    private final BuyOrderMapper buyOrderMapper;
    private final PayConfigMapper payConfigMapper;

    @Override
    public Map<String, Object> createDiamondOrder(DiamondRechargeVo diamondRechargeVo, UserInfoVo userInfoVo, String payType) {
        Map<String, Object> result = new HashMap<>();
        String orderNo = DateUtil.format(DateUtil.date(), DatePattern.PURE_DATETIME_MS_FORMAT) + RandomUtil.randomNumbers(6);
        try {
            // 创建订单
            MemberOrder memberOrder = getOrder(diamondRechargeVo, userInfoVo, orderNo);
            memberOrderMapper.insert(memberOrder);

            JSONObject json = JSONUtil.parseObj(getPayUrl(orderNo, payType, diamondRechargeVo.getRechargeAmount()));

            if ("0".equals(json.getStr("status"))) {
                result.put("orderNo", orderNo);
                result.put("payUrl", JSONUtil.parseObj(json.getStr("result")).get("payUrl"));
            }

        } catch (Exception e) {
            log.error("充值钻石支付失败：{}", e.getMessage());
            throw new RuntimeException("充值钻石支付异常：" + e.getMessage());
        } finally {
            // 更改订单状态为支付失败
            memberOrderMapper.update(null, new LambdaUpdateWrapper<MemberOrder>()
                .set(MemberOrder::getOrderStatus, "3")
                .eq(MemberOrder::getOrderNo, orderNo));
        }

        return result;
    }

    private static MemberOrder getOrder(DiamondRechargeVo diamondRechargeVo, UserInfoVo userInfoVo, String orderNo) {
        MemberOrder memberOrder = new MemberOrder();
        memberOrder.setUserId(userInfoVo.getId());
        memberOrder.setProductId(diamondRechargeVo.getId());
        memberOrder.setOrderName("充值钻石");
        memberOrder.setOrderNo(orderNo);
        memberOrder.setOrderDescription("充值：" + diamondRechargeVo.getRechargeValue() + "钻石，赠送：" + diamondRechargeVo.getGiftValue());
        memberOrder.setOrderAmount(diamondRechargeVo.getRechargeAmount());
        memberOrder.setOrderType("0");
        return memberOrder;
    }

    @Override
    public Map<String, Object> createMemberOrder(MemberInfoVo memberInfoVo, UserInfoVo userInfoVo, String payType) {
        Map<String, Object> result = new HashMap<>();
        String orderNo = DateUtil.format(DateUtil.date(), DatePattern.PURE_DATETIME_MS_FORMAT) + RandomUtil.randomNumbers(6);
        try {
            // 创建订单
            MemberOrder memberOrder = getMemberOrder(memberInfoVo, userInfoVo, orderNo);
            memberOrderMapper.insert(memberOrder);

            JSONObject json = JSONUtil.parseObj(getPayUrl(orderNo, payType, memberInfoVo.getMemberAmount()));

            if ("0".equals(json.getStr("status"))) {
                result.put("orderNo", orderNo);
                result.put("payUrl", JSONUtil.parseObj(json.getStr("result")).get("payUrl"));
            }
        } catch (Exception e) {
            log.error("开通会员支付失败：{}", e.getMessage());
            throw new RuntimeException("开通会员支付异常：" + e.getMessage());
        } finally {
            // 更改订单状态为支付失败
            memberOrderMapper.update(null, new LambdaUpdateWrapper<MemberOrder>()
                .set(MemberOrder::getOrderStatus, "3")
                .eq(MemberOrder::getOrderNo, orderNo));
        }
        return result;
    }

    private static MemberOrder getMemberOrder(MemberInfoVo memberInfoVo, UserInfoVo userInfoVo, String orderNo) {
        MemberOrder memberOrder = new MemberOrder();
        memberOrder.setUserId(userInfoVo.getId());
        memberOrder.setProductId(memberInfoVo.getId());
        memberOrder.setOrderName("开通：" + memberInfoVo.getMemberName());
        memberOrder.setOrderNo(orderNo);
        memberOrder.setOrderDescription(userInfoVo.getNickName() + "开通" + memberInfoVo.getMemberName());
        memberOrder.setOrderAmount(memberInfoVo.getMemberAmount());
        memberOrder.setOrderType("1");
        return memberOrder;
    }

    @Override
    public Map<String, Object> orderNotify(OrderNotifyBo orderNotifyBo) {
        Map<String, Object> result = new HashMap<>();

        MemberOrder order = memberOrderMapper.selectOne(
            new LambdaUpdateWrapper<MemberOrder>().eq(
                MemberOrder::getOrderNo, orderNotifyBo.getMerOrderTid()
            ));
        // 更改订单状态为回调的支付状态
        memberOrderMapper.update(null, new LambdaUpdateWrapper<MemberOrder>()
            .set(MemberOrder::getOrderStatus, orderNotifyBo.getStatus())
            .set(MemberOrder::getUpdateTime, new Date())
            .eq(MemberOrder::getOrderNo, order.getOrderNo()));

        UserInfo userInfo = userInfoMapper.selectById(order.getUserId());

        // 状态 0=待处理 1=成功 2=失败 3=异常 4=超时关闭
        if ("1".equals(orderNotifyBo.getStatus())) {
            // 订单类型（0-充值钻石、1-开通会员）
            if ("0".equals(order.getOrderType())) {
                DiamondRecharge diamondRecharge = diamondRechargeMapper.selectById(order.getProductId());
                BigDecimal diamond = userInfo.getDiamond().add(new BigDecimal(orderNotifyBo.getMoney())).add(new BigDecimal(diamondRecharge.getGiftValue()));
                userInfo.setDiamond(diamond);
                userInfoMapper.updateById(userInfo);

                DiamondConsumeRecord diamondConsumeRecord = new DiamondConsumeRecord();
                diamondConsumeRecord.setUserId(userInfo.getId());
                diamondConsumeRecord.setConsumeName("充值");
                diamondConsumeRecord.setConsumeDiamond(new BigDecimal(orderNotifyBo.getMoney()));
                diamondConsumeRecord.setConsumeType("0");
                diamondConsumeRecordMapper.insert(diamondConsumeRecord);

            } else if ("1".equals(order.getOrderType())) {
                MemberInfoVo memberInfoVo = memberInfoMapper.selectVoById(order.getProductId());
                // 更新用户信息 会员类型（0-普通会员、1-网格会员）
                if ("0".equals(memberInfoVo.getMemberType())) {
                    // 判断用户是否开通过普通会员
                    if ("1".equals(userInfo.getIsMember())) {
                        userInfo.setIsMember("0");
                        userInfo.setMemberLevel(MemberLevelEnum.fromCode(memberInfoVo.getMemberLevel()).getDescription());
                        userInfo.setMemberExpireTime(queryByLevel(memberInfoVo.getMemberLevel()));
                        userInfoMapper.updateById(userInfo);
                    } else {
                        userInfo.setIsMember("0");
                        userInfo.setMemberLevel(MemberLevelEnum.fromCode(memberInfoVo.getMemberLevel()).getDescription());
                        userInfo.setMemberExpireTime(queryByLevelAndDate(memberInfoVo.getMemberLevel(), userInfo.getMemberExpireTime()));
                        userInfoMapper.updateById(userInfo);
                    }
                } else {
                    // 判断用户是否开通过网格会员
                    if ("1".equals(userInfo.getIsGridMember())) {
                        userInfo.setIsGridMember("0");
                        userInfo.setGridMemberLevel(MemberLevelEnum.fromCode(memberInfoVo.getMemberLevel()).getDescription());
                        userInfo.setGridMemberExpireTime(queryByLevel(memberInfoVo.getMemberLevel()));
                        userInfoMapper.updateById(userInfo);
                    } else {
                        userInfo.setIsMember("0");
                        userInfo.setGridMemberLevel(MemberLevelEnum.fromCode(memberInfoVo.getMemberLevel()).getDescription());
                        userInfo.setGridMemberExpireTime(queryByLevelAndDate(memberInfoVo.getMemberLevel(), userInfo.getGridMemberExpireTime()));
                        userInfoMapper.updateById(userInfo);
                    }
                }
            }
            result.put("orderNo", order.getOrderNo());
            result.put("userId", order.getUserId());

        }
        return result;

    }

    @Override
    public void payOrderByDiamond(UserBuyOrderBo buyOrderBo) {
        Long userId = LoginHelper.getUserId();
        UserInfo userInfo = userInfoMapper.selectById(userId);
        // 钻石支付，判断余额是否充足
        if (userInfo.getDiamond().compareTo(buyOrderBo.getOrderAmount()) < 0) {
            throw new RuntimeException("钻石余额不足");
        }
        String orderNo = DateUtil.format(DateUtil.date(), DatePattern.PURE_DATETIME_MS_FORMAT) + RandomUtil.randomNumbers(6);
        String productName = "";
        String productCover = "";
        if ("2".equals(buyOrderBo.getOrderType())) {
            NovelChapterVo chapterVo = novelChapterMapper.selectVoById(buyOrderBo.getProductId());
            if (chapterVo == null) {
                throw new RuntimeException("商品ID传输有误");
            }
            if (buyOrderBo.getOrderAmount().compareTo(chapterVo.getConsumeDiamond()) != 0) {
                throw new RuntimeException("购买金额输入错误");
            }
            NovelInfoVo novelInfoVo = novelInfoMapper.selectVoById(chapterVo.getNovelId());
            if (novelInfoVo != null) {
                // 校验是否购买
                queryBuyOrder(novelInfoVo.getId(), chapterVo.getId(), buyOrderBo.getOrderType());

                productName = novelInfoVo.getNovelName();
                productCover = novelInfoVo.getNovelCover();
                insertBuyOrder(buyOrderBo, orderNo, productName, productCover, novelInfoVo.getId(), chapterVo.getId());
            }
        } else if ("3".equals(buyOrderBo.getOrderType())) {
            CaricatureChapterVo chapterVo = caricatureChapterMapper.selectVoById(buyOrderBo.getProductId());
            if (chapterVo == null) {
                throw new RuntimeException("商品ID传输有误");
            }
            if (buyOrderBo.getOrderAmount().compareTo(chapterVo.getConsumeDiamond()) != 0) {
                throw new RuntimeException("购买金额输入错误");
            }
            CaricatureInfoVo caricatureInfoVo = caricatureInfoMapper.selectVoById(chapterVo.getCaricatureId());
            if (caricatureInfoVo != null) {
                // 校验是否购买
                queryBuyOrder(caricatureInfoVo.getId(), chapterVo.getId(), buyOrderBo.getOrderType());

                productName = caricatureInfoVo.getCaricatureName();
                productCover = caricatureInfoVo.getCaricatureCover();
                insertBuyOrder(buyOrderBo, orderNo, productName, productCover, caricatureInfoVo.getId(), chapterVo.getId());
            }
        } else {
            VideoInfoVo videoInfoVo = videoInfoMapper.selectVoById(buyOrderBo.getProductId());
            if (videoInfoVo == null) {
                throw new RuntimeException("商品ID传输有误");
            }
            if (buyOrderBo.getOrderAmount().compareTo(videoInfoVo.getConsumeDiamond()) != 0) {
                throw new RuntimeException("购买金额输入错误");
            }
            // 校验是否购买
            queryBuyOrder(videoInfoVo.getId(), null, buyOrderBo.getOrderType());

            productName = videoInfoVo.getVideoName();
            productCover = videoInfoVo.getVideoCover();
            insertBuyOrder(buyOrderBo, orderNo, productName, productCover, videoInfoVo.getId(), null);
        }

        // 购买支付，更新用户信息和钻石记录
        BigDecimal diamond = userInfo.getDiamond().subtract(buyOrderBo.getOrderAmount());
        userInfo.setDiamond(diamond);
        userInfoMapper.updateById(userInfo);

        DiamondConsumeRecord diamondConsumeRecord = new DiamondConsumeRecord();
        diamondConsumeRecord.setUserId(userInfo.getId());
        diamondConsumeRecord.setConsumeName(productName);
        diamondConsumeRecord.setConsumeDiamond(buyOrderBo.getOrderAmount());
        diamondConsumeRecord.setConsumeType("1");
        diamondConsumeRecordMapper.insert(diamondConsumeRecord);
    }

    private void queryBuyOrder(Long productId, Long chapterId, String orderType) {
        BuyOrder buyOrder = buyOrderMapper.selectOne(new LambdaQueryWrapper<BuyOrder>()
            .eq(BuyOrder::getProductId, productId)
            .eq(ObjectUtil.isNotNull(chapterId), BuyOrder::getChapterId, orderType)
            .eq(BuyOrder::getOrderType, orderType));
        if (buyOrder != null) {
            throw new RuntimeException("您已购买过");
        }
    }

    private void insertBuyOrder(UserBuyOrderBo buyOrderBo, String orderNo, String productName, String productCover, Long id, Long chapterId) {
        BuyOrder buyOrder = new BuyOrder();
        buyOrder.setUserId(LoginHelper.getUserId());
        buyOrder.setProductId(id);
        buyOrder.setChapterId(chapterId);
        buyOrder.setProductName(productName);
        buyOrder.setProductCover(productCover);
        buyOrder.setOrderAmount(buyOrderBo.getOrderAmount());
        buyOrder.setOrderType(buyOrderBo.getOrderType());
        buyOrder.setOrderNo(orderNo);
        buyOrder.setOrderStatus("1");
        buyOrderMapper.insert(buyOrder);
    }

    /**
     * 支付
     */
    private String getPayUrl(String orderNo, String payType, BigDecimal money) {
        PayConfig payConfig = payConfigMapper.selectOne(new LambdaQueryWrapper<PayConfig>()
            .eq(PayConfig::getStatus, "0")
            .last("1"));
        if (payConfig == null) {
            throw new RuntimeException("未进行支付配置");
        }
        // 订单支付开始
        TreeMap<String, Object> map = new TreeMap<>();
        map.put("channelCode", payType);
        try {
            // 使用URL类解析URL
            URL url = new URL(payConfig.getNotifyUrl());
            // getHost() 方法返回主机名
            String clientIp = url.getHost();
            map.put("clientIp", clientIp);
            // 打印提取的IP地址
            System.out.println("Extracted IP: " + clientIp);
        } catch (MalformedURLException e) {
            throw new RuntimeException("未进行支付配置");
        }
        map.put("mid", payConfig.getAppId());
        map.put("merOrderTid", orderNo);
        map.put("money", money);
        map.put("notifyUrl", payConfig.getNotifyUrl());
        String sign = MapUtil.join(map, "&", "=");
        sign += "&" + payConfig.getSecret();
        log.info("支付签名:{}", sign);
        map.put("sign", SecureUtil.md5(sign));
        String resultStr = HttpUtil.post(payConfig.getPayUrl(), map);
        log.info("支付返回结果:{}", resultStr);
        return resultStr;
    }

    /**
     * 根据会员级别获取会员到期时间
     */
    private String queryByLevel(String level) {
        DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
        // 获取当前日期
        LocalDate now = LocalDate.now();
        return getTime(level, now, dateTimeFormatter);
    }

    /**
     * 根据会员级别获取会员到期时间
     */
    private String queryByLevelAndDate(String level, String date) {
        DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
        // 获取当前日期
        LocalDate startDate = LocalDate.parse(date, dateTimeFormatter);
        return getTime(level, startDate, dateTimeFormatter);
    }

    private String getTime(String level, LocalDate startDate, DateTimeFormatter dateTimeFormatter) {
        String time = "";
        if ("0".equals(level)) {
            // 计算天会员到期时间
            LocalDate dailyExpiration = startDate.plusDays(1);
            time = dailyExpiration.format(dateTimeFormatter);
        } else if ("1".equals(level)) {
            // 计算月会员到期时间
            LocalDate monthlyExpiration = startDate.plusMonths(1);
            time = monthlyExpiration.format(dateTimeFormatter);
        } else if ("2".equals(level)) {
            // 计算年度会员到期时间
            LocalDate yearlyExpiration = startDate.plusYears(1);
            time = yearlyExpiration.format(dateTimeFormatter);
        } else {
            time = "2099-01-01";
        }
        return time;
    }

}
